/**
 * Copyright (c) Huawei Technologies Co., Ltd. 1987-2021. All rights reserved.
*/

package com.gitee.fufu669.aspect;

import com.gitee.fufu669.common.CacheKeyCommon;
import com.gitee.fufu669.config.exception.CacheEmptyInstance;
import com.gitee.fufu669.service.CacheService;
import com.gitee.fufu669.utils.CacheAopUtil;
import com.gitee.fufu669.utils.CacheHtmlUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;

// 注解
@Lazy
// 注解
@Aspect
// 组件注解
@Component
/** @author wangfupeng */
/**
 * TODO
*/
public class CacheFetchLaterAop {

    /**
     * TODO
    */
    public static final Logger logger = LoggerFactory.getLogger(CacheFetchLaterAop.class);

    // 注解
    @Autowired
    // 定义
    CacheService cacheService;

    // 注解
    @Autowired
    // 注解
    @Qualifier(value="threadPoolTaskExecutorCacheFetchLater")
    // 定义
    ThreadPoolTaskExecutor threadPoolTaskExecutor;

    // 注解
    @Around("@annotation(com.gitee.fufu669.aspect.CacheFetchLater)")
    /**
     * TODO
    */
    public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // 赋值
        int refreshSeconds = CacheKeyCommon.CACHEFETCHLATERAOP_REFRESH_EXPIRE_SECONDS;
        // 赋值
        String methodName = null;
        // 赋值
        int expireSeconds = CacheKeyCommon.CACHESERVICE_REDIS_DEFAULT_EXPIRED_SECONDS_1_WEEK;
        // 赋值
        String description = "";
        // 赋值
        int printGetValueLog = CacheKeyCommon.DEFAULT_YES_VALUE;
        // 尝试下面的代码
        try {
            // 字符串赋值
            String targetName = proceedingJoinPoint.getTarget().getClass().getName();
            // TODO
            methodName = proceedingJoinPoint.getSignature().getName();
            // TODO
            Object[] arguments = proceedingJoinPoint.getArgs();
            // TODO
            Class targetClass = Class.forName(targetName);
            // TODO
            Method[] methods = targetClass.getMethods();
            // 遍历
            for (Method method : methods) {
                // 判断
                if (method.getName().equals(methodName)) {
                    // TODO
                    refreshSeconds = method.getAnnotation(CacheFetchLater.class).refreshSeconds();
                    // TODO
                    expireSeconds = method.getAnnotation(CacheFetchLater.class).expireSeconds();
                    // TODO
                    description = method.getAnnotation(CacheFetchLater.class).description();
                    // TODO
                    printGetValueLog = method.getAnnotation(CacheFetchLater.class).printGetValueLog();
                    // 跳出
                    break;
                }
            }
        // 捕捉异常
        } catch (Exception e) {
            logger.info(e.toString());
        }
        logger.info("%%%%%%CacheFetchLaterAop:aroundMethod:description:"+ description+"%%%%%%");
        // 字符串赋值
        String cacheKey = CacheAopUtil.getCacheKey(proceedingJoinPoint);
        // TODO
        Object value = cacheService.getValue(cacheKey, printGetValueLog);
        // 判断是否非空
        if (value != null) {
            // 赋值
            boolean refreshFlag = true;
            // TODO
            refreshFlag = CacheAopUtil.isRefreshFlag(refreshSeconds, cacheKey, cacheService);
            // 判断
            if (refreshFlag) {
                // 创建
                CustomThreadToRunAndSaveToRedis customThreadToRunAndSaveToRedis = new CustomThreadToRunAndSaveToRedis();
                // TODO
                customThreadToRunAndSaveToRedis.setProceedingJoinPoint(proceedingJoinPoint);
                // TODO
                customThreadToRunAndSaveToRedis.setExpireSeconds(expireSeconds);
                // TODO
                customThreadToRunAndSaveToRedis.setDescription(description);
                // 执行
                threadPoolTaskExecutor.execute(customThreadToRunAndSaveToRedis);
            }
            // 判断
            if(value.getClass().equals(Class.forName("com.gitee.fufu669.config.exception.CacheEmptyInstance"))){
                // 返回
                return null;
            }
            /**获取当前方法的返回的类名，然后如果是Long类型，碰着值是integer，要强转一哈，否则会报错。*/
            Signature signature = proceedingJoinPoint.getSignature();
            // TODO
            Class returnType = ((MethodSignature) signature).getReturnType();
            // TODO
            value = getValueFromReturnType(value, returnType);
            // 返回
            return value;
        // 否则
        } else {
            // 尝试下面的代码
            try {
                // TODO
                value = proceedingJoinPoint.proceed();
                // 判断是否是空
                if (value == null) {
                    // TODO
                    Signature signature = proceedingJoinPoint.getSignature();
                    // TODO
                    Class returnType = ((MethodSignature) signature).getReturnType();
                    // 判断
                    if (returnType.equals(Class.forName("java.util.List"))) {
                        // 创建
                        cacheService.setValue(cacheKey, new ArrayList<>());
                        // TODO
                        cacheService.expire(cacheKey, expireSeconds);
                    // 判断
                    } else if (returnType.equals(Class.forName("java.util.Map"))) {
                        // 创建
                        cacheService.setValue(cacheKey, new HashMap<String, String>());
                        // TODO
                        cacheService.expire(cacheKey, expireSeconds);
                    // 否则
                    }else {
                        // 判断
                        if(returnType.isInterface()){
                            // 创建
                            cacheService.setValue(cacheKey, new CacheEmptyInstance());
                            // TODO
                            cacheService.expire(cacheKey, expireSeconds);
                        // 否则
                        }else {
                            // TODO
                            cacheService.setValue(cacheKey, returnType.newInstance());
                            // TODO
                            cacheService.expire(cacheKey, expireSeconds);
                        }
                    }
                // 否则
                } else {
                    // TODO
                    cacheService.setValue(cacheKey, value);
                    // TODO
                    cacheService.expire(cacheKey, expireSeconds);
                }
                // 返回
                return value;
            // 捕捉异常
            } catch (Throwable throwable) {
                logger.info(throwable.getMessage(), throwable);
                // 返回
                return value;
            }
        }
    }

    /**
     * TODO
    */
    public static Object getValueFromReturnType(Object value, Class returnType) throws ClassNotFoundException {
        // 判断
        if (returnType.equals(Class.forName("java.lang.Long"))) {
            // 转换值
            value = Long.valueOf("" + value);
        // 判断
        } else if (returnType.equals(Class.forName("java.lang.Double"))) {
            // 转换值
            value = Double.valueOf("" + value);
        // 判断
        } else if (returnType.equals(Class.forName("java.lang.Float"))) {
            // 转换值
            value = Float.valueOf("" + value);
        // 判断
        } else if (returnType.equals(Class.forName("java.lang.Byte"))) {
            // 转换值
            value = Byte.valueOf("" + value);
        // 判断
        } else if (returnType.equals(Class.forName("java.lang.Short"))) {
            // 转换值
            value = Short.valueOf("" + value);
        }
        // 返回
        return value;
    }

    /**
     * TODO
    */
    public class CustomThreadToRunAndSaveToRedis implements Runnable {
        // TODO
        private ProceedingJoinPoint proceedingJoinPoint;
        // 赋值
        private int expireSeconds = CacheKeyCommon.CACHESERVICE_REDIS_DEFAULT_EXPIRED_SECONDS_1_WEEK;
        // 赋值
        private String description = "";

        /**
         * TODO
        */
        public void setProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) {
            // 赋值
            this.proceedingJoinPoint = proceedingJoinPoint;
        }

        /**
         * TODO
        */
        public void setExpireSeconds(int expireSeconds) {
            // 赋值
            this.expireSeconds = expireSeconds;
        }

        /**
         * TODO
        */
        public void setDescription(String description) {
            // 赋值
            this.description = description;
        }

        /**
         * TODO
        */
        public void run() {
            // 字符串赋值
            String targetName = proceedingJoinPoint.getTarget().getClass().getName();
            // 字符串赋值
            String methodName = proceedingJoinPoint.getSignature().getName();
            logger.info("%%%%%%CacheFetchLaterAop:multiThread:☆☆☆start☆☆☆:Classname:"+ CacheHtmlUtil.getLastStringSplitHtml(targetName, "\\.")+":methodName:"+methodName+":description:"+description+"%%%%%%");
            // 赋值
            String cacheKey = null;
            // 尝试下面的代码
            try {
                // 赋值
                Object value = null;
                // 尝试下面的代码
                try {
                    // TODO
                    value = proceedingJoinPoint.proceed();
                // 捕捉异常
                } catch (Throwable throwable) {
                    logger.info(throwable.getMessage(), throwable);
                    // 返回
                    return;
                }
                // TODO
                cacheKey = CacheAopUtil.getCacheKey(proceedingJoinPoint);
                // 判断是否是空
                if (value == null) {
                    // TODO
                    Signature signature = proceedingJoinPoint.getSignature();
                    // TODO
                    Class returnType = ((MethodSignature) signature).getReturnType();
                    // 尝试下面的代码
                    try {
                        // TODO
                        cacheService.setValue(cacheKey, returnType.newInstance());
                        // TODO
                        cacheService.expire(cacheKey, expireSeconds);
                    // 捕捉异常
                    } catch (Exception e) {
                        logger.info(e.getMessage(), e);
                        // 创建
                        cacheService.setValue(cacheKey, new CacheEmptyInstance());
                        // TODO
                        cacheService.expire(cacheKey, expireSeconds);
                    }
                // 否则
                } else {
                    // TODO
                    cacheService.setValue(cacheKey, value);
                    // TODO
                    cacheService.expire(cacheKey, expireSeconds);
                }
            // 捕捉异常
            } catch (Exception e) {
                logger.info(e.getMessage(), e);
            // 最终执行
            } finally {
                // TODO
                cacheService.unlock(CacheKeyCommon.LOCK + cacheKey);
                logger.info("%%%%%%CacheFetchLaterAop:multiThread:★★★end★★★:Classname:"+CacheHtmlUtil.getLastStringSplitHtml(targetName, "\\.")+":methodName:"+methodName+":description:" + description + "%%%%%%");
            }
        }
    }

}
